#ifndef _UTIL_HPP
#define	_UTIL_HPP

#include <algorithm>
#include <string>
#include <cmath>
#include <set>
#include "lex_cast.h"
#include "Interval.hpp"


/*	Tillader nem og hurtig udskrivning af værdien af udtryk.
 */
#define debugf(x)	{std::cout << __PRETTY_FUNCTION__ << ":" << __LINE__ << ":\t " #x " = '" << (x) << "'" << std::endl;}


template <typename T, typename Function>
Function for_each(T obj, Function f) 
{
	for (auto it = obj.begin(); it != obj.end(); ++it)
		f(*it);
}

template <typename T, typename Function>
T filter(T obj, Function pred) 
{
	T ret;
	for (auto it = obj.begin(); it != obj.end(); ++it)
		if (pred(*it))  ret.insert(ret.end(), *it);
	return ret;
}


//template <typename T>
//inline T max(const T& a, const T& b) {
//	return (a > b) ? a : b;
//}
//
//template <typename T>
//inline T min(const T& a, const T& b) {
//	return (a < b) ? a : b;
//}




template <typename T>
std::set<T> set_remove(std::set<T> initial, std::set<T> to_be_removed) 
{
	std::set<T> ret = initial;
	
	typedef typename std::set<T>::iterator iter_t;
	for (iter_t it = to_be_removed.begin(); it != to_be_removed.end(); ++it) {
		T elem = *it;
		if (initial.count(elem)) {
			ret.erase(elem);
		}
	}
	
	return ret;
}

template <typename T>
std::set<T> set_union(std::set<T> arg1, std::set<T> arg2) 
{
	std::set<T> ret;
	ret.insert(arg1.begin(), arg1.end());
	ret.insert(arg2.begin(), arg2.end());
	return ret;
}

template <typename T>
std::set<T> set_intersection(std::set<T> arg1, std::set<T> arg2) 
{
	std::set<T> ret;

	typedef typename std::set<T>::iterator iter_t;
	for (iter_t it = arg1.begin(); it != arg1.end(); ++it) {
		T elem = *it;
		if (arg2.count(elem)) {	// both in arg1 and arg2, add to ret
			ret.insert(elem);
		}
	}

	return ret;
}

template <typename T>
bool subset(std::set<T> arg1, std::set<T> arg2) {
	return std::includes(arg2.begin(), arg2.end(), arg1.begin(), arg1.end());
}


/**	Opretholder statistik omkr. det totale antal oprettede objekter, samt
 *	antallet af nuværende levende objekter.
 *
 * Kilde:
 *	http://en.wikipedia.org/w/index.php?title=CRTP&oldid=339419375#Object_counter
 */
template <class T>
class counter {
public:
	counter() 
	:	my_number(objects_created)
	{
		++objects_created;
		++objects_alive;
	}

	virtual ~counter() {
		--objects_alive;
	}

	int this_number() const {
		return this->my_number;
	}

private:
	int my_number;
	static int objects_created;
	static int objects_alive;
};
template <class T> int counter<T>::objects_created(0);
template <class T> int counter<T>::objects_alive(0);


#endif	/* _UTIL_HPP */

